#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "bitmaps.h"
#include "bloques.h"
#include "constants.h"
#include "ext2_fs.h"

/*
 * Lee un bitmap de bloques/inodos
 * Recibe el numero de bloque donde comienza el bitmap
 * Si lee un bitmap de bloques recibe como tamaño del bitmap el tamaño de un bloque
 * Si lee un bitmap de inodos recibe como tamaño del bitmap la cantidad de bloques de inodos por grupo
 * */
unsigned char * readBitmap(void *address, int num_block){
	unsigned char *bitmap = (unsigned char *)malloc(BLOCK_SIZE);
	void *start_address = address + BLOCK_SIZE * num_block;
	memcpy(bitmap, start_address, BLOCK_SIZE);

	return bitmap;
}

//TODO: Funciona, hay que hacer que retorne el arrayLibres, no tengo tiempo ahora :P

void buscarBloquesLibresGrupo(void *address, int groupId){
	ext2_super_block *super_block = readSuperBlock(address);
	int bloqueInicialGrupo = FIRST_BLOCK_OF_GROUP(super_block,groupId);
	ext2_group_desc *group_desc = readGroupDescriptor(address, groupId);
	unsigned char *bitmap = readBitmap(address, group_desc->bg_block_bitmap);
	printf("Bitmap de bloques del Grupo: %d\n",groupId);
	buscarLibres(bitmap, group_desc->bg_free_blocks_count, bloqueInicialGrupo, BLOCK_SIZE);
	free(group_desc);
	free(super_block);
}

void buscarInodosLibresGrupo(void *address, int groupId){
	ext2_super_block *super_block = readSuperBlock(address);
	int nodoInicialGrupo = FIRST_INODE_OF_GROUP(super_block,groupId);
	int tamBitmapInodos = INODE_BLOCKS_PER_GROUP(super_block);
	ext2_group_desc *group_desc = readGroupDescriptor(address, groupId);
	unsigned char *bitmap = readBitmap(address, group_desc->bg_inode_bitmap);
	printf("Bitmap de inodos del Grupo: %d\n",groupId);
	buscarLibres(bitmap,group_desc->bg_free_inodes_count,nodoInicialGrupo,tamBitmapInodos);
	free(group_desc);
	free(super_block);
}

/*
 * Busca ceros en el bitmap de bloques/inodos y devuelve un array de enteros con
 * los bloques/inodos libres.
 * Recibe la cantidad de bloques/inodos libres como dato del descriptor de grupo
 * Recibe el numero de bloque/inodo incial del grupo
 *
 */
void buscarLibres(unsigned char *bitmap, int libres, int num_inicial, int size_bitmap){
	int i = 0;
	int posArray = 0;
	int arrayLibres[libres];
	byte byte1;
	while (i<size_bitmap){
		if(!bitmap[i]){
			int j=1;
			while(j<9) {
				arrayLibres[posArray] = i * 8 + j + (num_inicial-1);
				posArray++;
				j++;
			}
		}
		else {
			memcpy(&byte1, &bitmap[i], 1);
			if(!byte1.bit1){
				arrayLibres[posArray] = i * 8 + 1 + (num_inicial-1);
				posArray++;
			}
			if(!byte1.bit2){
				arrayLibres[posArray] = i * 8 + 2 + (num_inicial-1);
				posArray++;
			}
			if(!byte1.bit3){
				arrayLibres[posArray] = i * 8 + 3 + (num_inicial-1);
				posArray++;
			}
			if(!byte1.bit4){
				arrayLibres[posArray] = i * 8 + 4 + (num_inicial-1);
				posArray++;
			}
			if(!byte1.bit5){
				arrayLibres[posArray] = i * 8 + 5 + (num_inicial-1);
				posArray++;
			}
			if(!byte1.bit6){
				arrayLibres[posArray] = i * 8 + 6 + (num_inicial-1);
				posArray++;
			}
			if(!byte1.bit7){
				arrayLibres[posArray] = i * 8 + 7 + (num_inicial-1);
				posArray++;
			}
			if(!byte1.bit8){
				arrayLibres[posArray] = i * 8 + 8 + (num_inicial-1);
				posArray++;
			}
		}
	i++;
	}
	mostrarLibres(arrayLibres,libres);
}

void mostrarLibres(int *arrayLibres, int libres){
	int i = 0;
	int inicial = arrayLibres[i];
	int final;
	while (i<libres){
		if(arrayLibres[i+1] == arrayLibres[i]+1){
			final = arrayLibres[i+1];
		}
		else{
			printf("Bloques Libres: %d - %d\n",inicial, final);
			inicial = arrayLibres[i+1];
			final = arrayLibres[i+1];
		}
		i++;
	}
}

/*
 * Cuenta libres para verificar con el descriptor, no hace falta
 */
int contarLibres(unsigned char *bitmap, int size_bitmap){
	int i= 0;
	int libres = 0;
	byte byte1;
	while (i<size_bitmap){
		if(!bitmap[i]){
			libres+=8;
		}
		else {
			memcpy(&byte1,&bitmap[i],1);
			if(!byte1.bit1) libres++;
			if(!byte1.bit2) libres++;
			if(!byte1.bit3) libres++;
			if(!byte1.bit4) libres++;
			if(!byte1.bit5) libres++;
			if(!byte1.bit6) libres++;
			if(!byte1.bit7) libres++;
			if(!byte1.bit8) libres++;
		}
	i++;
	}
	printf("Cantidad de Bloques Libres: %d\n", libres);
	return libres;
}


